from fastapi import FastAPI, Request, HTTPException, Query
from fastapi.responses import Response, JSONResponse, StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
import logging
import json
import warnings
from typing import Optional
from config import settings
from proxy import proxy

# 配置日志
logging.basicConfig(
    level=getattr(logging, settings.log_level.upper()),
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# 如果启用，则过滤SSL相关的警告
if settings.ignore_ssl_warnings:
    # 过滤SSL关闭超时的警告
    warnings.filterwarnings("ignore", message=".*SSL shutdown timed out.*")
    
    # 创建自定义日志过滤器
    class SSLWarningFilter(logging.Filter):
        def filter(self, record):
            # 过滤包含SSL关闭错误的日志记录
            message = record.getMessage()
            if "SSL shutdown timed out" in message:
                return False
            if "Connection lost: SSL shutdown timed out" in message:
                return False
            if "ClientConnectionError" in message and "SSL shutdown" in message:
                return False
            return True
    
    # 将过滤器应用到根日志记录器
    root_logger = logging.getLogger()
    root_logger.addFilter(SSLWarningFilter())
    
    # 也应用到常见的HTTP客户端日志记录器
    for logger_name in ['httpx', 'httpcore', 'h11', 'h2']:
        http_logger = logging.getLogger(logger_name)
        http_logger.addFilter(SSLWarningFilter())

# 创建FastAPI应用
app = FastAPI(
    title="OpenAI Base URL 代理服务",
    description="一个通用的OpenAI API代理服务，支持多种后端。API密钥由调用方在请求头中提供。",
    version="1.0.0"
)

# 添加CORS中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/")
async def root():
    """根路径，返回服务信息"""
    return {
        "service": "OpenAI Base URL 代理服务",
        "description": "通用的AI API代理服务，API密钥由调用方传入",
        "version": "1.0.0",
        "backends": list(settings.backends.keys()),
        "status": "running",
        "usage": {
            "auth": "在Authorization头中传入API密钥",
            "example": "Authorization: Bearer sk-your-api-key"
        }
    }

@app.get("/health")
async def health_check():
    """增强的健康检查接口，包含协程状态信息"""
    try:
        # 获取代理服务的健康状态
        proxy_health = await proxy.health_check()
        
        # 添加服务级别的健康信息
        service_health = {
            "service": "OpenAI Base URL 代理服务",
            "version": "1.0.0",
            "status": "healthy",
            "timestamp": __import__('datetime').datetime.now().isoformat(),
            "proxy_status": proxy_health
        }
        
        # 如果代理不健康，整体服务状态也设为不健康
        if proxy_health.get("status") != "healthy":
            service_health["status"] = "unhealthy"
            
        return service_health
        
    except Exception as e:
        logger.error(f"健康检查失败: {e}")
        return {
            "service": "OpenAI Base URL 代理服务",
            "status": "error",
            "error": str(e),
            "timestamp": __import__('datetime').datetime.now().isoformat()
        }

@app.get("/backends")
async def list_backends():
    """列出所有可用的后端服务"""
    backends_info = {}
    for name, config in settings.backends.items():
        backends_info[name] = {
            "base_url": config.get("base_url", ""),
            "auth_header": config.get("auth_header", "authorization"),
            "auth_prefix": config.get("auth_prefix", "Bearer "),
            "description": f"使用 {config.get('auth_header', 'authorization')} 头进行认证"
        }
    return {
        "backends": backends_info,
        "note": "API密钥需要在请求头中提供，代理服务会自动转换认证格式"
    }

@app.api_route("/{backend}/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
async def proxy_openai_api(
    backend: str,
    path: str,
    request: Request
):
    """
    代理OpenAI API请求
    
    Args:
        backend: 后端服务名称 (openai, azure, claude等)
        path: API路径
        request: FastAPI请求对象
    """
    try:
        # 检查后端是否支持
        if backend not in settings.backends:
            raise HTTPException(
                status_code=400, 
                detail=f"不支持的后端服务: {backend}。支持的后端: {list(settings.backends.keys())}"
            )
        
        # 读取请求体
        body = await request.body()
        
        # 转发请求
        response_data = await proxy.forward_request(
            method=request.method,
            path=path,
            headers=dict(request.headers),
            body=body if body else None,
            backend=backend
        )
        
        # 如果是流式响应，直接返回StreamingResponse
        if isinstance(response_data, StreamingResponse):
            return response_data
        
        # 构建普通响应
        status_code = response_data["status_code"]
        headers = response_data["headers"]
        content = response_data["content"]
        
        # 过滤响应头
        filtered_headers = {}
        allowed_response_headers = [
            "content-type", "content-length", "content-encoding",
            "cache-control", "expires", "etag"
        ]
        
        for key, value in headers.items():
            if key.lower() in allowed_response_headers:
                filtered_headers[key] = value
        
        return Response(
            content=content,
            status_code=status_code,
            headers=filtered_headers
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"代理请求失败: {e}")
        raise HTTPException(status_code=500, detail=f"内部服务器错误: {str(e)}")

@app.api_route("/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
async def proxy_default_api(
    path: str,
    request: Request,
    backend: Optional[str] = Query("openai", description="指定后端服务")
):
    """
    默认的代理接口，不需要在路径中指定后端
    
    Args:
        path: API路径
        request: FastAPI请求对象
        backend: 后端服务名称，默认为openai
    """
    return await proxy_openai_api(backend, path, request)

@app.on_event("startup")
async def startup_event():
    """应用启动事件"""
    logger.info("OpenAI代理服务启动")
    logger.info(f"支持的后端服务: {list(settings.backends.keys())}")
    logger.info("API密钥由调用方在请求头中提供")

@app.on_event("shutdown")
async def shutdown_event():
    """应用关闭事件"""
    logger.info("OpenAI代理服务关闭")
    await proxy.close()

if __name__ == "__main__":
    import uvicorn
    
    # 构建uvicorn配置
    uvicorn_config = {
        "app": "main:app",
        "host": settings.proxy_host,
        "port": settings.proxy_port,
        "reload": True,
        "log_level": settings.log_level.lower()
    }
    
    # 如果启用HTTPS，添加SSL配置
    if settings.enable_https:
        if settings.ssl_certfile and settings.ssl_keyfile:
            uvicorn_config.update({
                "ssl_certfile": settings.ssl_certfile,
                "ssl_keyfile": settings.ssl_keyfile,
            })
            if settings.ssl_ca_certs:
                uvicorn_config["ssl_ca_certs"] = settings.ssl_ca_certs
        else:
            logger.warning("HTTPS已启用但未配置SSL证书文件")
    
    uvicorn.run(**uvicorn_config) 